package dao.impl;

import dao.DBdao;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class DBdaoImpl implements DBdao {
    //新版驱动名字为 driverClass=“com.mysql.cj.jdbc.Driver”
    private static final String JDBC_Driver = "com.mysql.cj.jdbc.Driver";//jdbc驱动名称
    private static final String DB_Url = "jdbc:mysql://localhost:3306/newdb?serverTimezone=UTC";//数据库url
    private static final String DB_User = "root";//数据库的用户名
    private static final String DB_Password = "mysql@123";//数据库的密码

    //连接池
    ArrayList<Connection> pool=new ArrayList<Connection>();

    //获取数据库连接应该使用连接池，否则每次都要重新连接
    /**
     * @discription 获取数据库连接
     * @return Connection
     */
    @Override
    public synchronized Connection getConnection() {
        Connection connection = null;
        //如果连接池中有连接对象
        if(!pool.isEmpty()){
            return pool.remove(0);//返回一个Connection
        }else{
            for (int i = 0; i < 20; i++) {
                try {
                    //1- 注册JDBC驱动
                    Class.forName(JDBC_Driver);
                    //2- 连接数据库
                    //System.out.println("开始连接数据库...");
                    connection = DriverManager.getConnection(DB_Url,DB_User,DB_Password);

                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
                //往连接池中放入Connection
                pool.add(connection);
            }
        }
        return pool.remove(0);
    }

    /**
     * @discription 关闭连接
     */
    public synchronized void close(Connection con){
        if(con!=null){
            pool.add(con);
        }
    }

    /**
     * @discription 查询
     * @param sql SQL语句
     * @param param SQL语句中的通配符对应的值，如果SQL语句中没有通配符，该数组为null
     * @return List<Map<String, Object>>
     */
    @Override
    public List<Map<String, Object>> select(String sql, Object[] param) {

        Connection con=getConnection();
        PreparedStatement ps=null;
        ResultSet rs=null;
        List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();

        try {
            ps=con.prepareStatement(sql);
            //通配符不为空
            if (param!=null){
                for(int i=1;i<=param.length;i++){
                    ps.setObject(i,param[i-1]);//设置SQL语句中的对应的通配符
                }
            }
            rs=ps.executeQuery();//查询
            //MetaData:描述数据的数据
            //getMetaData包括了数据的字段名称、类型以及数目等
            ResultSetMetaData rm=rs.getMetaData();
            //列数
            int count =rm.getColumnCount();
            while(rs.next()){
                //一条记录
                Map<String,Object> OnePieceData=new HashMap<String,Object>();
                //此处String为列名，Object为对应该列的值，for循环扫描每一列
                for(int i=1;i<=count;i++){
                    OnePieceData.put(rm.getColumnName(i).toLowerCase(),rs.getObject(i));
                   /*
                   * rs.getObject(i)等同于rs.getObject(rm.getColumnName(i))
                   * 前者是通过列数获取，后者是通过列名
                   * */
                }
                //把记录放进List
                list.add(OnePieceData);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            close(con);//关闭连接
        }

        return list;
    }

    /**
     * @discription 新增、修改、删除处理
     * @param sql SQL语句
     * @param params SQL语句中所有通配符的值
     * @return 处理结果，true为成功，false为失败
     */
    public synchronized boolean updateByParams(String sql,Object[] params){
        boolean flag=false;
        Connection con=getConnection();
        PreparedStatement ps=null;
        try{
            ps=con.prepareStatement(sql);
            if(params!=null){
                for(int i=1;i<=params.length;i++){
                    ps.setObject(i,params[i-1]);
                }
                int count=ps.executeUpdate();//更新的行数
                if(count>0)
                    flag=true;
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }finally {
            close(con);//关闭连接
        }
        return flag;
    }
}
